#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "buffer.h"
#include "mem_allocator.h"

static inline void buffer_destroy(void *b)
{
	buffer_t _b = (buffer_t)b;
	if(_b->next)
		buffer_release(&(_b)->next);
	MEM_FREE(NULL,_b);
	b = 0;
}

static inline buffer_t buffer_create(uint8_t mt,uint32_t capacity)
{
	uint32_t size = sizeof(struct buffer) + capacity;
	buffer_t b = (buffer_t)MEM_ALLOC(NULL,size);		
	if(b)
	{
		b->size = 0;
		b->capacity = capacity;
		b->_refbase.refcount = 0;
		b->_refbase.mt = mt;
		b->_refbase.destroyer = buffer_destroy;	
	}
	return b;
}


buffer_t buffer_create_and_acquire(uint8_t mt,buffer_t b,uint32_t capacity)
{
	buffer_t nb = buffer_create(mt,capacity);
	return buffer_acquire(b,nb);
}

buffer_t buffer_acquire(buffer_t b1,buffer_t b2)
{
	if(b1 == b2)
		return b1;	
	if(b2)
		ref_increase(&b2->_refbase);
	if(b1)
		buffer_release(&b1);

	return b2;
}

void buffer_release(buffer_t *b)
{
	if(*b)
	{
		ref_decrease(&(*b)->_refbase);
		*b = 0;
	}
}

int buffer_read(buffer_t b,uint32_t pos,int8_t *out,uint32_t size)
{
	uint32_t copy_size;
	while(size)
	{
		if(!b)
			return -1;
		copy_size = b->size - pos;
		copy_size = copy_size > size ? size : copy_size;
		memcpy(out,b->buf + pos,copy_size);
		size -= copy_size;
		pos += copy_size;
		out += copy_size;
		if(pos >= b->size)
		{
			pos = 0;
			b = b->next;
		}
	}
	return 0;
}



